#include "Web.h"
#include "Tools.h"

CCScene* Web::scene()
{
	CCScene *sc = CCScene::create();
	Web *layer = Web::create();
	sc->addChild(layer);

	return sc;
}

bool Web::init()
{
	BaseLayer::init();

	testWeb();

	scheduleUpdate();
	setTouchEnabled(true);
	setTouchMode(kCCTouchesOneByOne);

	return true;
}

void Web::testWeb()
{
	b2Body* bodies[4] = { 0 };
	b2DistanceJoint* joints[8] = { 0 };
	b2Vec2 groundVec[4] = { b2Vec2(0, 0) };

	b2BodyDef bodyDef;
	bodyDef.type = b2_dynamicBody;

	b2PolygonShape boxShape;
	boxShape.SetAsBox(1.0f, 1.0f);

	b2FixtureDef fixDef;
	fixDef.density = 2.0f;
	fixDef.friction = 0.3f;
	fixDef.restitution = 1.0f;
	fixDef.shape = &boxShape;

	{	
		const b2Vec2 vec1 = Tools::convertTob2WorldSpace(ccp(winSize.width/3, winSize.height/3));
		bodyDef.position.Set(vec1.x, vec1.y);
		bodies[0] = m_world->CreateBody(&bodyDef);
		bodies[0]->CreateFixture(&fixDef);

		const b2Vec2 vec2 = Tools::convertTob2WorldSpace(ccp(winSize.width/3, winSize.height* 2/3));
		bodyDef.position.Set(vec2.x, vec2.y);
		bodies[1] = m_world->CreateBody(&bodyDef);
		bodies[1]->CreateFixture(&fixDef);

		const b2Vec2 vec3 = Tools::convertTob2WorldSpace(ccp(winSize.width * 2/3, winSize.height * 2/3));
		bodyDef.position.Set(vec3.x, vec3.y);
		bodies[2] = m_world->CreateBody(&bodyDef);
		bodies[2]->CreateFixture(&fixDef);

		const b2Vec2 vec4 = Tools::convertTob2WorldSpace(ccp(winSize.width* 2/3, winSize.height/3));
		bodyDef.position.Set(vec4.x, vec4.y);
		bodies[3] = m_world->CreateBody(&bodyDef);
		bodies[3]->CreateFixture(&fixDef);
	}
	
	b2RopeJointDef jointDef;
	{
		b2Vec2 distance, pA, pB;

		jointDef.collideConnected = true;

		groundVec[0] = Tools::convertTob2WorldSpace(ccp(0, 0));
		jointDef.bodyA = m_groundBody;
		jointDef.bodyB = bodies[0];
		jointDef.localAnchorA = m_groundBody->GetLocalPoint(b2Vec2(groundVec[0].x + 0.1f, groundVec[0].y + 0.1f));
		jointDef.localAnchorB = bodies[0]->GetLocalPoint(bodies[0]->GetWorldCenter());
		pA = jointDef.bodyA->GetWorldPoint(jointDef.localAnchorA);
		pB = jointDef.bodyB->GetWorldPoint(jointDef.localAnchorB);
		distance = pA - pB;
		jointDef.maxLength = distance.Length() + 1;
		joints[0] = (b2DistanceJoint*)m_world->CreateJoint(&jointDef);

		groundVec[1] = Tools::convertTob2WorldSpace(ccp(0, winSize.height));
		jointDef.bodyA = m_groundBody;
		jointDef.bodyB = bodies[1];
		jointDef.localAnchorA = m_groundBody->GetLocalPoint(b2Vec2(groundVec[1].x + 0.1f, groundVec[1].y - 0.1f));
		jointDef.localAnchorB = bodies[1]->GetLocalPoint(bodies[1]->GetWorldCenter());
		pA = jointDef.bodyA->GetWorldPoint(jointDef.localAnchorA);
		pB = jointDef.bodyB->GetWorldPoint(jointDef.localAnchorB);
		distance = pA - pB;
		jointDef.maxLength = distance.Length() + 1;
		joints[1] = (b2DistanceJoint*)m_world->CreateJoint(&jointDef);

		groundVec[2] = Tools::convertTob2WorldSpace(ccp(winSize.width, winSize.height));
		jointDef.bodyA = m_groundBody;
		jointDef.bodyB = bodies[2];
		jointDef.localAnchorA = m_groundBody->GetLocalPoint(b2Vec2(groundVec[2].x - 0.1f, groundVec[2].y - 0.1f));
		jointDef.localAnchorB = bodies[2]->GetLocalPoint(bodies[2]->GetWorldCenter());
		pA = jointDef.bodyA->GetWorldPoint(jointDef.localAnchorA);
		pB = jointDef.bodyB->GetWorldPoint(jointDef.localAnchorB);
		distance = pA - pB;
		jointDef.maxLength = distance.Length() + 1;
		joints[2] = (b2DistanceJoint*)m_world->CreateJoint(&jointDef);

		groundVec[3] = Tools::convertTob2WorldSpace(ccp(winSize.width, 0));
		jointDef.bodyA = m_groundBody;
		jointDef.bodyB = bodies[3];
		jointDef.localAnchorA = m_groundBody->GetLocalPoint(b2Vec2(groundVec[3].x - 0.1f, groundVec[3].y + 0.1f));
		jointDef.localAnchorB = bodies[3]->GetLocalPoint(bodies[3]->GetWorldCenter());
		pA = jointDef.bodyA->GetWorldPoint(jointDef.localAnchorA);
		pB = jointDef.bodyB->GetWorldPoint(jointDef.localAnchorB);
		distance = pA - pB;
		jointDef.maxLength = distance.Length() + 1;
		joints[3] = (b2DistanceJoint*)m_world->CreateJoint(&jointDef);

		jointDef.bodyA = bodies[0];
		jointDef.bodyB = bodies[1];
		jointDef.localAnchorA = bodies[0]->GetLocalPoint(bodies[0]->GetWorldCenter());
		jointDef.localAnchorB = bodies[1]->GetLocalPoint(bodies[1]->GetWorldCenter());
		pA = jointDef.bodyA->GetWorldPoint(jointDef.localAnchorA);
		pB = jointDef.bodyB->GetWorldPoint(jointDef.localAnchorB);
		distance = pA - pB;
		jointDef.maxLength = distance.Length();
		joints[4] = (b2DistanceJoint*)m_world->CreateJoint(&jointDef);

		jointDef.bodyA = bodies[1];
		jointDef.bodyB = bodies[2];
		jointDef.localAnchorA = bodies[1]->GetLocalPoint(bodies[1]->GetWorldCenter());
		jointDef.localAnchorB = bodies[2]->GetLocalPoint(bodies[2]->GetWorldCenter());
		pA = jointDef.bodyA->GetWorldPoint(jointDef.localAnchorA);
		pB = jointDef.bodyB->GetWorldPoint(jointDef.localAnchorB);
		distance = pA - pB;
		jointDef.maxLength = distance.Length();
		joints[5] = (b2DistanceJoint*)m_world->CreateJoint(&jointDef);

		jointDef.bodyA = bodies[2];
		jointDef.bodyB = bodies[3];
		jointDef.localAnchorA = bodies[2]->GetLocalPoint(bodies[2]->GetWorldCenter());
		jointDef.localAnchorB = bodies[3]->GetLocalPoint(bodies[3]->GetWorldCenter());
		pA = jointDef.bodyA->GetWorldPoint(jointDef.localAnchorA);
		pB = jointDef.bodyB->GetWorldPoint(jointDef.localAnchorB);
		distance = pA - pB;
		jointDef.maxLength = distance.Length();
		joints[6] = (b2DistanceJoint*)m_world->CreateJoint(&jointDef);

		jointDef.bodyA = bodies[3];
		jointDef.bodyB = bodies[0];
		jointDef.localAnchorA = bodies[3]->GetLocalPoint(bodies[3]->GetWorldCenter());
		jointDef.localAnchorB = bodies[0]->GetLocalPoint(bodies[0]->GetWorldCenter());
		pA = jointDef.bodyA->GetWorldPoint(jointDef.localAnchorA);
		pB = jointDef.bodyB->GetWorldPoint(jointDef.localAnchorB);
		distance = pA - pB;
		jointDef.maxLength = distance.Length();
		joints[7] = (b2DistanceJoint*)m_world->CreateJoint(&jointDef);
	}
}

void Web::update(float dt)
{
	m_world->Step(dt, 8, 1);
}

bool Web::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
	const CCPoint ptTouch = pTouch->getLocation();
	const b2Vec2 bodyVec = Tools::convertTob2WorldSpace(ptTouch);

	for (b2Body* b = m_world->GetBodyList(); b; b = b->GetNext()) {
		for (b2Fixture* fix = b->GetFixtureList(); fix; fix = fix->GetNext()) {
			if (fix->TestPoint(bodyVec)) {
				b2MouseJointDef jointDef;
				jointDef.bodyA = m_groundBody;
				jointDef.bodyB = b;
				jointDef.maxForce = 1000 * b->GetMass();
				jointDef.target = bodyVec;
				b->SetAwake(true);
				m_mouseJoint = (b2MouseJoint*)m_world->CreateJoint(&jointDef);

				CCLOG("=========Create mouse joint==========");

				return true;
			}
		}
	}

	return false;
}

void Web::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent)
{
	if (!m_mouseJoint) return;

	b2Vec2 mouseVec(Tools::convertTob2WorldSpace(pTouch->getLocation()));
	m_mouseJoint->SetTarget(mouseVec);
}

void Web::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
	if (m_mouseJoint) {
		m_world->DestroyJoint(m_mouseJoint);
		m_mouseJoint = NULL;

		CCLOG("=========Delete mouse joint==========");
	}
}